揭开 SwiftUI 神秘面纱
SwiftUI 如何看你写的代码
- identity: swiftUI 根据 ID 来识别相应的元素
- lifetime: swiftUI 更重存在的 View 和 数据
- dependence: swiftUI 理解什么时候什么原因去更新界面
swiftUI 根据这三个方面去决定什么时候怎样去改变什么。
identity
swiftUI 有两种不同的 identify。
- Explicit identify(明确的):用来自定义或者数据驱动的标识。
- 🌰1.List forEach 中使用的 id 来区分 item
- 🌰2.ScrollViewReader 滚动到某个 ID
- Structural identify(结构性):通过类型和在层级中的位置来区分。
- 🌰在 UIkit 中是使用指针来确定唯一的 View。但是 swiftUI 是指类型的并没有指针去确定谁是谁,所以 swiftUI 通过视图的层级结构的位置和类型来确定当前的 View 是哪一个。(所以尽量避免使用 AnyView,会擦除 View 的类型,降低性能)
lifetime
swiftUI view 的生命周期其实就是 identify 的生命周期,一旦 identify 变更,lifetime 就相应的结束了。
state lifetime

View value 是短暂的可能随时变更, View identify 是持久的。

State 在 view 初始化的时候就跟 View 的 identify 绑定在一起,即使之后 State 变更了,只要 identify 发生变化 State 也会被释放,产生新的 State 和 新 View 的 identify 绑定。
因此选择一个独一无二的 identify 能够避免很多奇怪的 bug 和动画。
dependence
dependence 的类型
- @Binding
- @State
- @Environment
- @StateObject
- @ObservedObject
- @EnvironmentObject
View 和 Dependence 之间的联系

不是树状的而是相互关联的图形关系,通过图形关系 swiftUI 能够更高效的去比对值类型的 View 然后去更新需要更新的 View。
Identifier stability
从上面的内容可以了解到一个稳定的 identify 可以带来的是:
- 直接影响到 lifetime
- 优化性能
- 减少 dependence 的变动
- 避免状态 State 的丢失
因此在实践中需要注意的情况:
- Explicit identify
- 避免使用 uuid 这种 identify 在 list 中一旦变更全部 item 全部更新
- 避免是用 slice 这种以顺序为 identify,当插入 item 不是在底部时,swiftUI 会处理插入到最后一个。
- 避免使用可能重复的 identify 可能导致不更新。
- Structural identify
- 相同的View避免使用没必要的分支,会导致 identify 的丢失。
- 尽量使用 inner modified(.opacity(show ? 1:0))
总结
SwiftUI 通过 Explicit identify 和 Structural identify 来确定唯一性,通过 identify 来控制 view 的生命周期,然后利用图形关系的依赖关系更高效的刷新视图。因此在 SwiftUI 中保证性能的最重要的一点就是保证 identify 的稳定性。